#pragma once

#include <iostream>
#include <memory>

namespace Protocol
{
    // 1. 结构化数据的序列和反序列化
// 2. 还要解决用户区分报文边界 --- 数据包粘包问题


// 1. 自定义协议
// 2. 成熟方案序列和反序列化
    const std::string ProtSep = " ";
    const std::string LineBreakSep = "\n";
// "len\n x op y\n" : \n 不属于报文的一部分， 约定

    std::string Encode(std::string &message)
    {
        std::string len = std::to_string(message.size());
        std::string package = len + LineBreakSep + message + LineBreakSep;
        return package;
    }

    // "len\n x op y\n" : \n 不属于报文的一部分， 约定
    // 我无法保证package就是一个独立的完整的报文
    bool Decode(std::string &package, std::string *message)
    {
        // 除了解包， 我还想判断报文的完整性， 能否正确处理具有"边界"的报文
        auto pos = package.find(LineBreakSep);
        if(pos == std::string::npos) return false;
        std::string lens = package.substr(0, pos);
        int messagelen = std::stoi(lens);
        int total = lens.size() + messagelen + 2 * LineBreakSep.size();
        if(package.size() < total)
        {
            return false;
        }
        //至少package内部一定有一个完整的报文！
        *message = package.substr(pos + LineBreakSep.size(), messagelen);
        package.erase(0, total);
        return true;
    }
    class Request
    {
    public:
        Request() :_data_x(0), _data_y(0), _oper(0)
        {
        }
        Request(int x, int y, char op) : _data_x(x), _data_y(y), _oper(op)
        {
        }
        void Debug()
        {
            std::cout << "data_x:" << _data_x << std::endl;
            std::cout << "data_y:" << _data_y << std::endl;
            std::cout << "oper:" << _oper << std::endl;
        }
        void Inc()
        {
            _data_x++;
            _data_y++;
        }
        bool Serialize(std::string *out)
        {
            *out = std::to_string(_data_x) + ProtSep + _oper + ProtSep + std::to_string(_data_y);
            return true;
        }

        bool DeSerialize(std::string &in) // "x op y"
        {
            auto left = in.find(ProtSep);
            if (left == std::string::npos)
            {
                std:: cout << "left" << std:: endl;
                return false;
            }

            auto right = in.rfind(ProtSep);
            if (right == std::string::npos)
            {
                std:: cout << "right" << std:: endl;
                return false;
            }

            _data_x = std::stoi(in.substr(0, left));
            _data_y = std::stoi(in.substr(right + ProtSep.size()));
            std::string oper = in.substr(left + ProtSep.size(), right - (left + ProtSep.size()));
            if (oper.size() != 1)
            {
                std::cout << "oper error" << std::endl;
                return false;
            }
            _oper = oper[0];
            return true;
        }
        int GetX() {return _data_x;}
        int GetY() {return _data_y;}
        char GetOper() {return _oper;}

    private:
        //"len\nx op y"  --- 报文的子描述字段
        // \n不属于报文的一部分，只是一种约定
        // _data_x _oper _data_y
        // 很多工作都是在做字符串处理
        int _data_x; // 第一个参数
        int _data_y; // 第二个参数
        char _oper;  // + - * / %
    };

    class Response
    {
    public:
        Response() : _result(0), _code(0)
        {
        }
        Response(int result, int code) : _result(result), _code(code)
        {
        }
        bool Serialize(std::string *out)
        {
            *out = std::to_string(_result) + ProtSep + std::to_string(_code);
            return true;
        }

        bool DeSerialize(std::string &in) //"_result _code"
        {
            auto pos = in.find(ProtSep);
            if (pos == std::string::npos)
                return false;
            _result = std::stoi(in.substr(0, pos));
            _code = std::stoi(in.substr(pos + ProtSep.size()));

            return true;
        }
        void SetResult(int res) {_result = res;}
        void SetCode(int code) {_code = code;}
        int GetResult()
        {
            return _result;
        }
        int GetCode()
        {
            return _code;
        }

    private:
        // "len\nresult _code"
        int _result; // 运算结果
        int _code;   // 运算状态
    };

    // 简单的工厂模式， 建造类设计模式
    class Factory
    {
    public:
        std::shared_ptr<Request> BuildRequest()
        {
            std::shared_ptr<Request> req = std::make_shared<Request>();
            return req;
        }

        std::shared_ptr<Request> BuildRequest(int x, int y, char op)
        {
            std::shared_ptr<Request> req = std::make_shared<Request>(x, y, op);
            return req;
        }
        std::shared_ptr<Response> BuildResponse()
        {
            std::shared_ptr<Response> resp = std::make_shared<Response>();
            return resp;
        }

        std::shared_ptr<Response> BuildResponse(int result, int code)
        {
            std::shared_ptr<Response> resp = std::make_shared<Response>(result, code);
            return resp;
        }
    };
}